package reserve

import (
	"time"
	"dhfshop/controllers/base"
	"dhfshop/models/consts"
	"dhfshop/models/reserve"
	//"strconv"
	"errors"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	"strings"
)

type PeriodController struct {
	base.BaseController
}

// fields: col1,col2,entity.col3; query: k:v,k:v; subquery: k:v,k:v; order_by: k:v,k:v
func (this *PeriodController) GetQueryPara() (string, string, string, map[string]string, map[string]string, []string, map[string]string, int, int, error) {
	query := make(map[string]string)
	subquery := make(map[string]string)
	fields := []string{}
	order_by := make(map[string]string)
	offset := 0 //default is 0
	limit := 10 //default is 50
	v := struct {
		Fields       string `form:"fields"`
		PageSize     int    `form:"page_size"`
		PageNo       int    `form:"page_no"`
		StartSoureAt string `form:"start_source_at"`
		EndSoureAt   string `form:"end_source_at"`
		Name         string `form:"name"`
		Query        string `form:"query"`
		Subquery     string `form:"subquery"`
		OrderBy      string `form:"order_by"`
	}{PageSize: 10, PageNo: 1}
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Range(v.PageSize, 1, 1000, "page_size")
	valid.Range(v.PageNo, 1, 1000, "page_no")
	passed, _ := valid.Valid(&v)
	if !passed {
		err := errors.New(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return v.StartSoureAt, v.EndSoureAt, v.Name, query, subquery, fields, order_by, offset, limit, err
	}
	v.PageNo = v.PageNo - 1 //为了计算offset
	if len(v.Fields) > 2 {
		fields = strings.Split(v.Fields, ",")
	}
	if len(v.Query) > 2 {
		for _, cond := range strings.Split(v.Query, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid query key/value pair")
				return v.StartSoureAt, v.EndSoureAt, v.Name, query, subquery, fields, order_by, offset, limit, err
			}
			k, v := kv[0], kv[1]
			query[k] = v
		}
	}
	if len(v.Subquery) > 2 {
		for _, cond := range strings.Split(v.Subquery, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid subquery key/value pair")
				return v.StartSoureAt, v.EndSoureAt, v.Name, query, subquery, fields, order_by, offset, limit, err
			}
			k, v := kv[0], kv[1]
			subquery[k] = v
		}
	}
	if len(v.OrderBy) > 2 {
		for _, cond := range strings.Split(v.OrderBy, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid order_by key/value pair")
				return v.StartSoureAt, v.EndSoureAt, v.Name, query, subquery, fields, order_by, offset, limit, err
			}
			k, v := kv[0], kv[1]
			order_by[k] = v
		}
	}
	offset = v.PageNo * v.PageSize
	limit = v.PageSize
	return v.StartSoureAt, v.EndSoureAt, v.Name, query, subquery, fields, order_by, offset, limit, nil
}

func (this *PeriodController) List() {
	start, end, _, query, _, fields, order_by, offset, limit, err := this.GetQueryPara()
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	//partnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	//query["partner_id"] = strconv.Itoa(partnerId)
	l, cnt, err := reserve.GetAllPeriods(start, end, query, fields, order_by, offset, limit)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	r := struct {
		TotalCount int64             `json:"total_count"`
		Period     []*reserve.Period `json:"periods"`
	}{TotalCount: cnt, Period: l}
	this.Data["json"] = r
	this.ServeJSON()
}

func (this *PeriodController) Update() {
	var v reserve.Period
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.PeriodId, "period_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	if v.SchemaId > 0 {
		v.Schema, _ = reserve.GetSchemaById(v.SchemaId)
	}
	updateFields, err := this.GetUpdateFields(v, "", "form", []string{"period_id"})
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	if len(updateFields) > 0 {
		err := reserve.UpdatePeriodById(&v, updateFields...)
		if err != nil {
			this.ServeError(err.Error())
			return
		}
	}
	rsp := struct {
		PeriodId int64     `json:"period_id"`
		Modified time.Time `json:"modified"`
	}{PeriodId: v.PeriodId, Modified: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *PeriodController) StatusUpdate() {
	partnerId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	v := struct {
		PartnerId int64  `form:"-"  valid:"Required"`
		SchemaId  int64  `form:"schema_id"`
		Start     string `form:"start"` //"2017-10-01"
		End       string `form:"end"`   //"2017-10-07"
		Status    int    `form:"status"`
	}{PartnerId: partnerId}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	startAt, err := time.Parse(consts.DATE_FORMAT, v.Start)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	endAt, err := time.Parse(consts.DATE_FORMAT, v.End)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	periodIds, err := reserve.GetPeriodIdsByDate(v.PartnerId, v.SchemaId, startAt, endAt)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	timeslotIds, err := reserve.GetTimeslotIdsByPeriods(v.PartnerId, v.SchemaId, periodIds)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	for _, periodId := range periodIds {
		if err = reserve.UpdatePeriodById(&reserve.Period{PeriodId: periodId, Status: v.Status}, "status"); err != nil {
			beego.Debug(err.Error())
		}
	}
	for _, timeslotId := range timeslotIds {
		if err = reserve.UpdateTimeslotById(&reserve.Timeslot{TimeslotId: timeslotId, Status: v.Status}, "status"); err != nil {
			beego.Debug(err.Error())
		}
	}
	rsp := struct {
		SchemaId int64     `json:"schema_id"`
		Modified time.Time `json:"modified"`
	}{SchemaId: v.SchemaId, Modified: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *PeriodController) Delete() {
	partnerId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	v := struct {
		PartnerId int64  `form:"-"  valid:"Required"`
		SchemaId  int64  `form:"schema_id"`
		PeriodId  int64  `form:"period_id"`
		Start     string `form:"start"`
		End       string `form:"end"`
	}{PartnerId: partnerId}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	err := reserve.DeletePeriodsByMultiCond(v.PartnerId, v.SchemaId, v.PeriodId, v.Start, v.End)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
		PartnerId int64     `json:"partner_id"`
		Modified  time.Time `json:"modified"`
	}{PartnerId: v.PartnerId, Modified: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}
